/*
 * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
 * that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.android.tests

import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.generators.util.TestGeneratorUtil.getMainClassName
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.NameUtils
import org.jetbrains.kotlin.utils.Printer
import java.io.File
import java.io.FileWriter

class TestInfo(val name: String, val fqName: FqName, val file: File)

class UnitTestFileWriter(
    private val flavourFolder: String,
    private val flavourName: String,
    private val generatedTestNames: MutableSet<String>
) {
    private val infos = arrayListOf<TestInfo>()

    fun addTests(info: List<TestInfo>) {
        infos.addAll(info)
    }

    fun generate() {
        FileWriter(File(flavourFolder, flavourName.replaceFirstChar(Char::uppercaseChar) + ".java").also { it.parentFile.mkdirs() }).use { suite ->
            val p = Printer(suite)
            p.println(
                """package ${CodegenTestsOnAndroidGenerator.testClassPackage};
                |
                |import ${CodegenTestsOnAndroidGenerator.baseTestClassPackage}.${CodegenTestsOnAndroidGenerator.baseTestClassName};
                |
                |/* This class is generated by ${getMainClassName()}. DO NOT MODIFY MANUALLY */
                |public class ${flavourName.replaceFirstChar(Char::uppercaseChar)} extends ${CodegenTestsOnAndroidGenerator.baseTestClassName} {
                |
            """.trimMargin()
            )
            p.pushIndent()

            infos.forEach { info ->
                generateTestMethod(
                    p,
                    generateTestName(info.file.name),
                    info.fqName.asString(),
                    StringUtil.escapeStringCharacters(info.file.path)
                )
            }

            p.popIndent()
            p.println("}")
        }
    }

    private fun generateTestName(fileName: String): String {
        var result = NameUtils.sanitizeAsJavaIdentifier(FileUtil.getNameWithoutExtension(StringUtil.capitalize(fileName)))

        var i = 0
        while (generatedTestNames.contains(result)) {
            result += "_" + i++
        }
        generatedTestNames.add(result)
        return result
    }

    private fun generateTestMethod(p: Printer, testName: String, className: String, filePath: String) {
        p.println("public void test$testName() throws Exception {")
        p.pushIndent()
        p.println("invokeBoxMethod($className.class, \"$filePath\", \"OK\");")
        p.popIndent()
        p.println("}")
        p.println()
    }

}